package cn.xenosp.server.common.tools.systemInfo;


import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.unit.DataUnit;
import cn.hutool.json.JSONObject;
import cn.hutool.system.oshi.OshiUtil;
import cn.xenosp.server.common.tools.systemInfo.dto.DisksInfo;
import cn.xenosp.server.common.tools.systemInfo.dto.NetworkInfo;
import cn.xenosp.server.common.tools.systemInfo.dto.OSInfo;
import cn.xenosp.server.common.tools.systemInfo.dto.OSRuntimeInfo;
import lombok.extern.slf4j.Slf4j;
import oshi.SystemInfo;
import oshi.hardware.*;
import oshi.software.os.FileSystem;
import oshi.software.os.OSFileStore;
import oshi.software.os.OperatingSystem;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.charset.Charset;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

/**
 * 系统信息获取工具类
 * 1.操作系统信息
 * 2.系统cpu使用信息
 * 3.系统内存信息
 * 4.系统卡流量信息
 * 5.磁盘使用量信息
 */
@Slf4j
public class SystemInfoUtil {
    /**
     * 对象                               方法                                                                          描述
     * SystemInfo                  getOperatingSystem()                                                        获取操作系统信息，OperatingSystem
     *                             getHardware()                                                               获取硬件信息，HardwareAbstractionLayer
     * OperatingSystem             getFamily()                                                                 获取操作系统名称，例如 Windows
     *                             getManufacturer()                                                           获取供货商，例如 Microsoft
     *                             getVersion()                                                                获取操作系统版本信息
     *                             getFileSystem()                                                             获取系统硬盘信息，FileSystem
     *                             getProcesses(int pId, OperatingSystem.ProcessSort var2)                     通过 进程id 获取进程信息，并设置排序方式，OSProcess[]
     *                             getProcess(int pId)                                                         通过 进程id 获取一个进程信息，OSProcess
     *                             getProcesses(Collection<Integer> pId)                                       获取多个进程信息，List<OSProcess>
     *                             getChildProcesses(int var1, int var2, OperatingSystem.ProcessSort var3)     获取子进程，OSProcess[]
     *                             getProcessId()                                                              获取进程id
     *                             getProcessCount()                                                           获取进程数量
     *                             getThreadCount()                                                            获取线程数
     *                             getNetworkParams()                                                          获取网络相关参数，NetworkParams
     * HardwareAbstractionLayer    getComputerSystem()                                                         获取计算机系统信息，ComputerSystem
     *                             getProcessor()                                                              获取处理器信息，CentralProcessor
     *                             getMemory()                                                                 获取内存信息，GlobalMemory
     *                             getPowerSources()                                                           获取电源信息，PowerSource
     *                             getDiskStores()                                                             获取硬件磁盘信息，HWDiskStore
     *                             getNetworkIFs()                                                             获取网络信息，NetworkIF
     *                             getDisplays()                                                               获取显示信息，Display
     *                             getSensors()                                                                获取传感器信息，Sensors
     *                             getUsbDevices(boolean var1)                                                 获取USB设备信息，UsbDevice
     * OperatingSystemVersion      getBuildNumber()                                                            获取内部编号
     *                             getCodeName()                                                               代码名称
     *                             getVersion()                                                                获取版本
     * FileSystem    getMaxFileDescriptors()    获取最大文件描述符
     * getOpenFileDescriptors()    获取打开文件描述符
     * getFileStores()    获取盘符相关信息
     * OSProcess    getName()    进程程序名称
     * getPath()    进程程序所在位置
     * getCommandLine()    获取命令行
     * getCurrentWorkingDirectory()    获取当前工作目录
     * getUser()    获取用户信息
     * getUserID()    获取用户id
     * getGroup()    获取组信息
     * getGroupID()    获取组id
     * getState()    状态
     * getProcessID()    获取进程id
     * getParentProcessID()    获取父进程id
     * getThreadCount()    获取线程数
     * getPriority()    优先级
     * getVirtualSize()    虚拟大小
     * getResidentSetSize()    实际使用物理内存
     *  getKernelTime()    内核时间
     *  getUserTime()    用户时间
     * getUpTime()    正常运行时间
     * getStartTime()    开始时间
     * getBytesRead()    读取字节
     * getBytesWritten()    写入字节
     * getOpenFiles()    打开文件数量
     * NetworkParams    getDnsServers()    获取域名地址
     * getHostName()    获取主机名
     * getDomainName()    获取域名
     * getIpv4DefaultGateway()    获取默认Ipv4
     * getIpv6DefaultGateway()    获取默认Ipv6
     * OSFileStore    getName()    磁盘名称
     * getVolume()    文件集
     * getLogicalVolume()    合理的文件集
     * getMount()    盘符
     * getDescription()    描述
     * getType()    类型
     * getUUID()    磁盘UUID
     * getUsableSpace()    可用空间
     * getTotalSpace()    总空间
     * ComputerSystem    getManufacturer()    获取制造商
     * getModel()    获取型号
     * getSerialNumber()    获取序列号
     * getFirmware()    获取固件信息，Firmware
     * getBaseboard()    获取外壳信息，Baseboard
     * Firmware    getManufacturer()    获取制造商信息
     * getName()    获取名称
     * getDescription()    获取描述信息
     * getVersion()    获取版本
     * getReleaseDate()    获取发布时间
     * Baseboard    getManufacturer()    获取制造商信息
     * getModel()    获取型号
     * getVersion()    获取版本信息
     * getSerialNumber()    获取序列号
     * CentralProcessor    getVendor()    获取供应商
     * getName()    获取cpu名称
     * getVendorFreq()    获取供应商频率
     * getProcessorID()    获取处理器id
     * getIdentifier()    获取标识符
     * isCpu64bit()    判断cpu是否为64位的
     * getStepping()    获取cpu步进
     * getModel()    获取型号
     * getFamily()    获取家族
     * getSystemCpuLoadBetweenTicks()    获取cpu负载间隔刻度
     * getSystemCpuLoadTicks()    获取cpu负载刻度
     * getSystemCpuLoad()    获取cpu负载
     * getSystemLoadAverage()    获取cpu平均负载
     * getSystemLoadAverage(int var1)    获取cpu平均负载
     * getProcessorCpuLoadBetweenTicks()    获取处理器cpu负载间隔刻度
     * getProcessorCpuLoadTicks()    获取处理器cpu负载刻度
     * getSystemUptime()    获取正常运行时间
     * getLogicalProcessorCount()    获取逻辑处理器数量
     * getPhysicalProcessorCount()    获取物理处理器数量
     * getPhysicalPackageCount()    获取物理包装数量
     * getContextSwitches()    获取上下文切换数量
     * getInterrupts()    获取中断
     * GlobalMemory    getTotal()    获取总内存
     * getAvailable()    获取可用系统运行内存
     * getSwapTotal()    获取可用虚拟总内存
     * getSwapUsed()    获取已用虚拟总内存
     * PowerSource    getName()    获取名称
     * getRemainingCapacity()    获取剩余容量
     * getTimeRemaining()    获取剩余时间
     * HWDiskStore    getName()    获取名称
     * getModel()    获取型号
     * getSerial()    获取序列号
     * getSize()    获取大小
     * getReads()    （读长）是高通量测序中一个反应获得的测序序列
     * getReadBytes()    读取字节
     * getWrites()    写长
     * getWriteBytes()    写入字节
     * getTransferTime()    获取转移时间
     * getPartitions()    获取分区，HWPartition
     * getTimeStamp()    获取时间戳
     * NetworkIF    getName()    获取名称
     * getDisplayName()    获取显示名称
     * getMTU()    获取最大传输单元
     * getMacaddr()    获取MAC地址
     * getIPv4addr()    获取IPv4
     * getIPv6addr()    获取IPv6
     * getBytesRecv()    获取接收字节数
     * getBytesSent()    获取发送字节数
     * getPacketsRecv()    获取接收数据包
     * getPacketsSent()    获取发送数据包
     * getInErrors()    是否可达，正常 0
     * getOutErrors()    响应错误，无错误 0
     *  getSpeed()    获取速率
     * getTimeStamp()    获取时间错
     * Display    getEdid()    中文名称扩展显示器识别数据
     * Sensors    getCpuTemperature()    获取CPU温度
     * getFanSpeeds()    获取风扇速度
     * getCpuVoltage()    获取CPU电压
     * UsbDevice    getName()    获取名称
     * getVendor()    获取供应商
     * getVendorId()    获取供应商id
     * getProductId()    获取商品id
     * getSerialNumber()    获取序列号
     * getConnectedDevices()    获取连接设备
     */
    private static SystemInfo systemInfo;

    private static HardwareAbstractionLayer abstractionLayer;

    private static OperatingSystem operatingSystem;

    private static CentralProcessor centralProcessor;

    private static GlobalMemory globalMemory;

    private static long[] oldTicks;

    private static Map<String, Long[]> networkInfoMap;

    private static List<NetworkIF> networkIFList;

    private static DecimalFormat df = new DecimalFormat("0.00");

    private SystemInfoUtil() {
    }


    static {
        try {
            systemInfo = new SystemInfo();
            abstractionLayer = systemInfo.getHardware();
            operatingSystem = systemInfo.getOperatingSystem();
            centralProcessor = abstractionLayer.getProcessor();
            globalMemory = abstractionLayer.getMemory();
            oldTicks = new long[CentralProcessor.TickType.values().length];
            networkInfoMap = new ConcurrentHashMap<>();
            networkIFList = getNetwork();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    enum NetworkType {
        /**
         * 当前网卡时间戳
         */
        TIME_STAMP(0),
        /**
         * 网卡总发送量
         */
        SEND(1),
        /**
         * 网卡总接收量
         */
        ACCEPT(2);
        private int index;

        NetworkType(int value) {
            this.index = value;
        }

        public int getIndex() {
            return index;
        }
    }

    /**
     * 获取磁盘列表信息
     *
     * @return
     */

    public static List<DisksInfo> getDisksList() {
        FileSystem fileSystem = operatingSystem.getFileSystem();
        List<OSFileStore> fileStores = fileSystem.getFileStores();
        List<DisksInfo> list = new ArrayList<>();
        for (int i = 0; i < fileStores.size(); i++) {
            OSFileStore osFileStore = fileStores.get(i);
            DisksInfo disksInfo = new DisksInfo();
            disksInfo.setDirName(osFileStore.getMount());
            String name = osFileStore.getName();
            disksInfo.setSysTypeName(name);
            disksInfo.setTypeName(osFileStore.getType());
            long total = osFileStore.getTotalSpace();
            long free = osFileStore.getUsableSpace();
            long used = total - free;
            if (used < 0) {
                // 有的挂载盘获取到的 free比total还大 不知是否是方法问题
                continue;
            }
            disksInfo.setTotal(total);
            disksInfo.setTotalStr(SystemInfoUtil.formatData(total));
            disksInfo.setFree(free);
            disksInfo.setFreeStr(SystemInfoUtil.formatData(free));
            disksInfo.setUsed(used);
            disksInfo.setUsedStr(SystemInfoUtil.formatData(used));
            if (total != 0) {
                disksInfo.setUsage(Double.parseDouble(df.format((double) used / total)));
                disksInfo.setUsageStr(SystemInfoUtil.formatRate(disksInfo.getUsage()));
            }
            list.add(disksInfo);
        }
        return list;
    }

    /**
     * 系统jvm信息
     */
    public static JSONObject jvm() {
        JSONObject cpuInfo = new JSONObject();
        Properties props = System.getProperties();
        Runtime runtime = Runtime.getRuntime();
        long jvmTotalMemoryByte = runtime.totalMemory();
        long freeMemoryByte = runtime.freeMemory();
        //jvm总内存
        cpuInfo.set("total", formatData(runtime.totalMemory()));
        //空闲空间
        cpuInfo.set("free", formatData(runtime.freeMemory()));
        //jvm最大可申请
        cpuInfo.set("max", formatData(runtime.maxMemory()));
        //vm已使用内存
        cpuInfo.set("user", formatData(jvmTotalMemoryByte - freeMemoryByte));
        //jvm内存使用率
        cpuInfo.set("usageRate", formatRate((jvmTotalMemoryByte - freeMemoryByte) * 1.0 / jvmTotalMemoryByte));
        //jdk版本
        cpuInfo.set("jdkVersion", props.getProperty("java.version"));
        //jdk路径
        cpuInfo.set("jdkHome", props.getProperty("java.home"));
        return cpuInfo;
    }

    /**
     * 获取网络接口NetworkIF对象列表
     *
     * @return
     */
    private static List<NetworkIF> getNetwork() {
        List<NetworkIF> list = new ArrayList<>();
        List<NetworkIF> networkIFs = abstractionLayer.getNetworkIFs();
        for (int i = 0; i < networkIFs.size(); i++) {
            NetworkIF networkIF = networkIFs.get(i);
            if (!networkIF.isKnownVmMacAddr()) {
                if (networkIF.getMacaddr() != null && networkIF.getIPv4addr().length > 0
                        && networkIF.getIPv6addr().length > 0) {
                    if (!networkInfoMap.containsKey(networkIF.getMacaddr())) {
                        networkIF.updateAttributes();
                        Long[] data = new Long[]{networkIF.getTimeStamp(), networkIF.getBytesSent(), networkIF.getBytesRecv()};
                        networkInfoMap.put(networkIF.getMacaddr(), data);
                    }
                    list.add(networkIF);
                }
            }
        }
        return list;
    }

    /**
     * 网卡实际的传输速率受多方面影响，具体如下：
     * 1、硬盘的读写（I/O）速度达不到。
     * 2、网卡本身性能差。
     * 3、交换机/（HUB）性能差。
     * 4、通讯线路条件质量差。
     * 5、网络性能差。
     * <p>
     * 一般情况下：
     * 网络条件比较好的网络利用率100Mbits的一般为：1/8(此方法默认)
     * 网络及各方面条件差的利用率一般为：1/12
     */
    public static List<NetworkInfo> getNetworkInfo() {
        networkIFList = getNetwork();
        List<NetworkInfo> list = new ArrayList<>();
        for (int i = 0; i < networkIFList.size(); i++) {
            NetworkIF networkIF = networkIFList.get(i);
            if (networkIF.updateAttributes()) {
                if (networkIF.getIPv4addr().length > 0 && networkIF.getIPv6addr().length > 0) {
                    NetworkInfo networkInfo = new NetworkInfo();
                    networkInfo.setIpv4Address(networkIF.getIPv4addr()[0]);
                    networkInfo.setIpv6Address(networkIF.getIPv6addr()[0]);
                    networkInfo.setMacAddress(networkIF.getMacaddr());
                    networkInfo.setNetworkName(networkIF.getName());

                    //计算
                    Long[] oldData = networkInfoMap.get(networkIF.getMacaddr());
                    long time = oldData[NetworkType.TIME_STAMP.getIndex()] - networkIF.getTimeStamp();
                    if (time == 0) {
                        continue;
                    }
                    long send = (oldData[NetworkType.SEND.getIndex()] - networkIF.getBytesSent()) * 8 / time * 1000;
                    long accept = (oldData[NetworkType.ACCEPT.getIndex()] - networkIF.getBytesRecv()) * 8 / time * 1000;
                    Long[] newData = new Long[]{networkIF.getTimeStamp(), networkIF.getBytesSent(), networkIF.getBytesRecv()};
                    networkInfoMap.put(networkInfo.getMacAddress(), newData);

                    //对象赋值
                    networkInfo.setTimeStamp(networkIF.getTimeStamp());
                    networkInfo.setSend(send);
                    networkInfo.setAccept(accept);
                    list.add(networkInfo);
                }
            }

        }
        return list;
    }

    /**
     * 获取系统运行信息
     *
     * @return
     * @throws InterruptedException
     */


    public static OSRuntimeInfo getOSRuntimeInfo() throws InterruptedException {
        OSRuntimeInfo osRuntimeInfo = new OSRuntimeInfo();
        osRuntimeInfo.setTimestamp(DateUtil.now());
        //cpu使用率
        osRuntimeInfo.setCpuUsage(getCpuRate());
        //cpu基准速度（GHz）
        osRuntimeInfo.setCpuMaxFreq(df.format(centralProcessor.getMaxFreq() / 1000000000.0) + " GHz");
        //cpu当前速度（GHz）
        long[] currentFreq = centralProcessor.getCurrentFreq();
        long avg = Arrays.stream(currentFreq).sum() / currentFreq.length;
        osRuntimeInfo.setCpuCurrentFreq(df.format(avg / 1000000000.0) + " GHz");
        //系统内存总量
        osRuntimeInfo.setTotalMemory(globalMemory.getTotal());
        //系统使用量
        osRuntimeInfo.setUsedMemory(globalMemory.getTotal() - globalMemory.getAvailable());
        //可用虚拟总内存
        osRuntimeInfo.setSwapTotalMemory(globalMemory.getVirtualMemory().getSwapTotal());
        //已用虚拟内存
        osRuntimeInfo.setSwapUsedMemory(globalMemory.getVirtualMemory().getSwapUsed());
        //磁盘信息
        osRuntimeInfo.setDisksList(getDisksList());
        //磁盘读取速率
        Map<String, Double> diskIo = getDiskIo();
        double diskReadRate = diskIo.get("diskReadRate") == null ? 0 : diskIo.get("diskReadRate");
        osRuntimeInfo.setDiskReadRate(diskReadRate);
        //磁盘写入速率
        double diskWriteRate = diskIo.get("diskWriteRate") == null ? 0 : diskIo.get("diskWriteRate");
        osRuntimeInfo.setDiskWriteRate(diskWriteRate);
        //网卡信息
        osRuntimeInfo.setNetworkList(getNetworkInfo());
        return osRuntimeInfo;
    }



    public static OSInfo getSystemInfo() {
        Properties props = System.getProperties();
        OSInfo osInfo = new OSInfo();
        //操作系统
        osInfo.setOs(props.getProperty("os.name"));
        //系统架构
        osInfo.setOsArch(props.getProperty("os.arch"));
        //java版本
        osInfo.setJavaVersion(props.getProperty("java.version"));
        //工作目录
        osInfo.setUserDir(props.getProperty("user.dir"));
        //CPU核数
        osInfo.setCpuCount(centralProcessor.getLogicalProcessorCount());
        //主机信息
        try {
            InetAddress address = InetAddress.getLocalHost();
            osInfo.setHost(address.getHostAddress());
            osInfo.setHostName(address.getHostName());
        } catch (UnknownHostException e) {
            log.error("主机信息获取失败");
        }
        //系统启动时间
        osInfo.setBootTime(getBootTime());
        return osInfo;
    }



    /**
     * @return cpuRate cpu使用率
     * @throws InterruptedException
     */
    public static double getCpuRate() throws InterruptedException {
        CentralProcessor processor = OshiUtil.getHardware().getProcessor();
        long[] prevTicks = processor.getSystemCpuLoadTicks();
        // 睡眠1s
        TimeUnit.SECONDS.sleep(1);
        long[] ticks = processor.getSystemCpuLoadTicks();
        long nice = ticks[CentralProcessor.TickType.NICE.getIndex()]
                - prevTicks[CentralProcessor.TickType.NICE.getIndex()];
        long irq = ticks[CentralProcessor.TickType.IRQ.getIndex()]
                - prevTicks[CentralProcessor.TickType.IRQ.getIndex()];
        long softirq = ticks[CentralProcessor.TickType.SOFTIRQ.getIndex()]
                - prevTicks[CentralProcessor.TickType.SOFTIRQ.getIndex()];
        long steal = ticks[CentralProcessor.TickType.STEAL.getIndex()]
                - prevTicks[CentralProcessor.TickType.STEAL.getIndex()];
        long cSys = ticks[CentralProcessor.TickType.SYSTEM.getIndex()]
                - prevTicks[CentralProcessor.TickType.SYSTEM.getIndex()];
        long user = ticks[CentralProcessor.TickType.USER.getIndex()]
                - prevTicks[CentralProcessor.TickType.USER.getIndex()];
        long iowait = ticks[CentralProcessor.TickType.IOWAIT.getIndex()]
                - prevTicks[CentralProcessor.TickType.IOWAIT.getIndex()];
        long idle = ticks[CentralProcessor.TickType.IDLE.getIndex()]
                - prevTicks[CentralProcessor.TickType.IDLE.getIndex()];
        long totalCpu = user + nice + cSys + idle + iowait + irq + softirq + steal;
        double d = 1.0 - (idle * 1.0 / totalCpu);
        return Double.parseDouble(df.format(d));
    }

    /**
     * 获取系统启动时间
     *
     * @return
     */
    public static String getBootTime() {
        String uptime = "";
        String os = System.getProperty("os.name").toLowerCase();
        try {
            if (os.contains("win")) {
                Process uptimeProc = Runtime.getRuntime().exec("net statistics Workstation");
                BufferedReader in = new BufferedReader(new InputStreamReader(uptimeProc.getInputStream(), Charset.forName("GBK")));
                String line;
                while ((line = in.readLine()) != null) {
                    if (line.startsWith("Statistics since")) {
                        SimpleDateFormat format = new SimpleDateFormat("'Statistics since' yyyy/MM/dd HH:mm:ss");
                        Date bootTime = format.parse(line);
                        uptime = DateUtil.format(bootTime, DatePattern.NORM_DATETIME_PATTERN);
                        break;
                    } else if (line.startsWith("统计数据开始于")) {
                        SimpleDateFormat format = new SimpleDateFormat("'统计数据开始于' yyyy/MM/dd HH:mm:ss");
                        Date bootTime = format.parse(line);
                        uptime = DateUtil.format(bootTime, DatePattern.NORM_DATETIME_PATTERN);
                        break;
                    }
                }
            } else if (os.contains("mac") || os.contains("nix") || os.contains("nux") || os.contains("aix")) {
                Process uptimeProc = Runtime.getRuntime().exec("uptime -s");
                BufferedReader in = new BufferedReader(new InputStreamReader(uptimeProc.getInputStream()));
                String line = in.readLine();
                if (line != null) {
                    uptime = line;
                }
            }
        } catch (Exception e) {
            log.error("获取系统启动时间异常: {}", e.getMessage());
        }
        return uptime;
    }

    /**
     * 获取磁盘读写速度（Kb/秒）
     *
     * @return
     */
    public static Map<String, Double> getDiskIo() {
        Map<String, Double> map = new HashMap<>();
        String os = System.getProperty("os.name").toLowerCase();
        try {
            double kbReadPerSec = 0;
            double kbWrittenPerSec = 0;
            if (os.contains("mac") || os.contains("nix") || os.contains("nux") || os.contains("aix")) {
                Process pos = Runtime.getRuntime().exec("iostat -d 1 2");
                BufferedReader reader = new BufferedReader(new InputStreamReader(pos.getInputStream()));
                String line;
                while ((line = reader.readLine()) != null) {
                    if (line.startsWith("Device") || line.startsWith("Linux")) {
                        // Skip the header line
                        continue;
                    }
                    // Split line into columns
                    String[] parts = line.trim().split("\\s+");
                    if (parts.length >= 6) {
                        String device = parts[0];
                        double tps = Double.parseDouble(parts[1]);
                        kbReadPerSec = Math.max(Double.parseDouble(parts[2]), kbReadPerSec);
                        kbWrittenPerSec = Math.max(Double.parseDouble(parts[3]), kbWrittenPerSec);

//                        System.out.println("Device: " + device);
//                        System.out.println("tps: " + tps);
//                        System.out.println("kB_read/s: " + kbReadPerSec);
//                        System.out.println("kB_wrtn/s: " + kbWrittenPerSec);
                    }
                }
            }
            map.put("diskReadRate", kbReadPerSec);
            map.put("diskWriteRate", kbWrittenPerSec);
        } catch (Exception e) {
            map.put("diskReadRate", 0D);
            map.put("diskWriteRate", 0D);
            log.error("获取磁盘传输速度异常: {}", e.getMessage());
        }
        return map;
    }

    /**
     * 格式化输出百分比
     *
     * @param rate 待格式化数据
     *
     * <pre>
     *     0.1234   -> 12.34%
     *     1.2      -> 120%
     * </pre>
     * @return
     */
    public static String formatRate(double rate) {
        return new DecimalFormat("#.##%").format(rate);
    }

    /**
     * 格式化输出大小 B/KB/MB...
     *
     * @param size 字节大小
     * @return
     */
    public static String formatData(long size) {
        if (size <= 0L) {
            return "0B";
        } else {
            int digitGroups = Math.min(DataUnit.UNIT_NAMES.length - 1, (int) (Math.log10((double) size) / Math.log10(1024.0D)));
            return (new DecimalFormat("#,##0.##")).format((double) size / Math.pow(1024.0D, (double) digitGroups)) + " " + DataUnit.UNIT_NAMES[digitGroups];
        }
    }
}


